import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
import matplotlib
import math
import csv

class Performance():
    
    def __init__(self, transactions, df, result):
        self._transactions=transactions
        self._initialdf=df
        #self._tranpd = pd.DataFrame(columns=['datebuy','pricebuy', 'datesell', 'pricesell'])  #待定
        self._df = result#pd.DataFrame(columns=['date','cash_all'])  # 调整initialdf
        
    def ratioandplot(self):

        matplotlib.rc("font",family='YouYuan')   #允许作图中显示中文字体
        
        # 运行结果：投入资金量、最后的总资产、回测期间
        initial_cash = self._df.iloc[0,1]
        final_cash = self._df.iloc[-1,1]
        start_date = self._df.iloc[0,0]
        end_date = self._df.iloc[-1,0]

        # 年化收益率，复利计算，以（1+收益/本金）**（250/期间）-1
        annual_profit = (1+(self._df.tail(1)['cash_all'].values[0]/self._df.head(1)['cash_all'].values[0]-1))**(250/self._df.shape[0]) - 1  #shape[0]计算行数

        # 日收益率
        df_copy=self._df.copy()
        df_copy["daliy_ratio"] = df_copy['cash_all'].pct_change()
        df_copy.fillna(0, inplace=True) 

        # 平均涨幅与收益波动率
        retyd = df_copy["daliy_ratio"].mean()*250
        
        # （年化）夏普比，需要每天的持仓，不仅仅是交易.
        # 描述股票或组合在单位风险下的所能获得超额收益的程度。它将一只标的或组合的风险归一化，便于更好的比较组合之间的有效性。
        # 数值越高代表考虑风险的情况下股票或组合表现越好。
        rf=0.03                               # 取10年期国债的收益率 
        volatility = df_copy["daliy_ratio"].std() * math.sqrt(250)  # 计算组合收益的标准差
        sharpe = (annual_profit-rf)/volatility

        # 最大回撤:描述股票或组合历史表现中从某高点开始最大的下跌比例。最大回撤通常越小越好
        highest_close = df_copy['cash_all'].max()
        df_copy['dropdown']=(1-df_copy['cash_all']/highest_close)
        maxdrawdown = df_copy['dropdown'].max()

        # 胜率，记得改
       # VictoryRatio = ((self._tranpd.pricesell - self._tranpd.pricebuy)>0).mean()
        
        # 计算月均交易次数
        self._transactions['year_month']=self._transactions['日期'].apply(lambda x:str(x)[:6])
        month=1
        for roll in range(self._transactions.shape[0]-1):
            if self._transactions.iloc[roll,-1] != self._transactions.iloc[roll+1,-1]:
                month += 1
        monthtran=self._transactions.shape[0]/month
        
        # 上涨概率
        def status(x):
            if x>0:
                return 1
            else:
                return 0
            
        df_copy['up_ratio'] = df_copy['daliy_ratio'].map(status)
        count=df_copy['up_ratio'].value_counts()
        up_precent=count[1]/(count[1]+count[0])
        

        # 单日最大亏损
        revenue_loss=[]
        for i in range(1,df_copy.shape[0]):
            a=df_copy.iloc[i,1]-df_copy.iloc[i-1,1]
            revenue_loss.append(a)
        maxloss = min(revenue_loss)
        
        # 作图1：资金变化图
        df_copy['cum'] = (1 + df_copy["daliy_ratio"]).cumprod()
        df_copy.plot(kind="line", y=['cash_all'], x_compat=True, title="总资产走势图")  #x_compat=True不缩放

        # 作图2：日收益率走势
        df_copy.plot(kind="line", y=['daliy_ratio'], x_compat=True, title="日收益率走势图")

        # 作图3：累计日收益率走势图
        df_copy.plot(kind="line", y=['cum'], x_compat=True, title="累积日收益率图")  

        # 作图4：策略净值与基准净值走势图
        benchmark_strategy = pd.read_excel("./input_try/benchmark_new.xls", header=0)
        benchmark_strategy.set_index("date",inplace=True)
        df_copy.set_index("date",inplace=True)
        benchmark_strategy["benchmark_ratio"] = benchmark_strategy.benchmark/benchmark_strategy.benchmark[0]
        benchmark_strategy["stra"]=df_copy["cash_all"]
        for i in range(df_copy.shape[0]):
            benchmark_strategy.iloc[i,2]=df_copy.iloc[i,0]
        benchmark_strategy["strategy_ratio"] = benchmark_strategy.stra/benchmark_strategy.stra[0]
        benchmark_strategy["RS"] = benchmark_strategy.strategy_ratio/benchmark_strategy.benchmark_ratio
        benchmark_strategy = benchmark_strategy.fillna(0)
        benchmark_strategy.plot(kind="line", y=['benchmark_ratio','strategy_ratio','RS'], x_compat=True, title="策略净值与基准净值走势图")

        # 信息比率：描述股票或组合相对于某一标的残差收益的收益风险比。
        # 通常来讲，股票或组合的信息比率越高，表明股票或组合在承担单位残差风险的情况下获取的残差收益越高，表现越好
        benchmark_strategy["change_ratio"]=benchmark_strategy["benchmark"].pct_change()  # 指数的日收益率
        benchmark_strategy["daliy_ratio"]=benchmark_strategy['stra'].pct_change()
        benchmark_strategy.fillna(0, inplace=True)
        benchmark_strategy["diff"]=benchmark_strategy["daliy_ratio"]-benchmark_strategy["change_ratio"]  # 股票日收益与指数日收益的差额
        benchmark_strategy.fillna(0, inplace=True)
        annual_mean = benchmark_strategy["diff"].mean() * 250
        annual_std = benchmark_strategy["diff"].std() * math.sqrt(250)
        info = annual_mean / annual_std
        
        # 计算：beta值,代表某股票走势与大盘的相关程度，它代表股票价格被大盘所解释的权重
        beta=benchmark_strategy["daliy_ratio"].cov(benchmark_strategy["change_ratio"])/benchmark_strategy["change_ratio"].var()
        
        # 输出
        print('------------------------------')
        print('投入资金量：',round(initial_cash,2))
        print('最终总资产：',round(final_cash,2))
        print('回测期间：',start_date,'to',end_date)
        print('-----------策略评价-----------')
        print('夏普比为:',round(sharpe,2))
        print('年化收益率为:{}%'.format(round(annual_profit*100,2)))
        print("平均涨幅为:{}%".format(round(retyd*100,2)))
        print("收益波动率为:{}%".format(round(volatility*100,2)))
        print("信息比率为：{}%".format(round(info*100,2)))
        print("beta值为：",round(beta,2))
        #print('胜率为：{}%'.format(round(VictoryRatio*100,2)))  # 记得改
        print('最大回撤率为：{}%'.format(round(maxdrawdown*100,2)))
        print('单日最大亏损为:',round(maxloss,2)) 
        print('上涨概率为：{}%'.format(round(up_precent*100,2)))
        print('总交易次数：',round(self._transactions.shape[0],2))
        print('月均交易次数为：{}(买卖合计)'.format(round(monthtran,2)))
        
        
        # 以上结果的dataframe显示
        result = {'Sharp':sharpe,
              'RetYearly':annual_profit,
                'Meanchange':retyd,
                'Volatility':volatility,
                'Information_ratio':info,
                'Beta':beta,
              #'WinRate':VictoryRatio,   #记得改
              'Maxdrawdown':maxdrawdown,
              'maxlossOnce':maxloss,  # 记得改
                'Up_precent':up_precent,
                'Totalnum':self._transactions.shape[0],
              'Monthnum':round(monthtran,2)}   
        
        result = pd.DataFrame.from_dict(result,orient='index').T
        
        # 策略逐年收益、基准逐年收益、逐年超额收益
        benchmark_strategy.reset_index("date", inplace=True)
        benchmark_strategy['year'] = benchmark_strategy['date'].apply(lambda x:str(x)[:4])
        
        benchmark_peryear = benchmark_strategy.benchmark.groupby(benchmark_strategy.year).last()/benchmark_strategy.benchmark.groupby(benchmark_strategy.year).first() - 1
        strategy_peryear = benchmark_strategy.strategy_ratio.groupby(benchmark_strategy.year).last()/benchmark_strategy.strategy_ratio.groupby(benchmark_strategy.year).first() - 1
        excess_ret = strategy_peryear - benchmark_peryear
        
        result_peryear = pd.concat([strategy_peryear,benchmark_peryear,excess_ret],axis = 1)
        result_peryear.columns = ["strategy_peryear","benchmark_peryear","excess_ret"]
        result_peryear = result_peryear.T

        print("-----------表格展示------------")
        print(result)
        print("-------------------------------")
        print(result_peryear)
        print('-----------图形展示------------')
        df_copy.to_csv("./daliy_change.csv")   
        benchmark_strategy.to_csv("./benchmark_strategy.csv")

        plt.show()
        return result,result_peryear

transactions=pd.read_csv("./input_try/日志表.csv",encoding="utf-8", header=0)
df=pd.read_csv("./input_try/持仓记录表.csv",encoding="utf-8", header=0)
result=pd.read_csv("./input_try/result.csv",encoding="utf-8", header=0) #input_try>python 1(1).py
myper=Performance(transactions,df,result)
myper.ratioandplot()
